home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Topik / Topik - Disk 37 - Games 3 (19xx)(Topik Public Domain)(PD)[WB].zip / Topik - Disk 37 - Games 3 (19xx)(Topik Public Domain)(PD)[WB].adf / RUMMY / SOURCE / autoturn.c.pp / autoturn.c
C/C++ Source or Header  |  1991-02-24  |  23KB  |  805 lines

  1. /* AUTOTURN.C
  2.  * This contains the functions for the program to decide what to do
  3.  */
  4.  
  5. #include    <proto/all.h>
  6. #include    <stdlib.h>
  7. #include    <math.h>
  8. #include    <intuition/intuition.h>
  9. #include    <string.h>
  10. #include    "defns.h"
  11. #include    "externs.h"
  12.  
  13.  
  14. VOID    autoturn(cp,np,pp)
  15. struct    playerinfo    *cp,*np,*pp;
  16. {
  17.     register    USHORT    i,n,p,takefup,cc=cp->nchld,gtemp;
  18.     register    struct    condset    *s;
  19.     char    buf[3];
  20.     /* deselect fup,fdp*/
  21.     gtemp = RemoveGList(wind,&stdgad[FUPG],2);
  22.     RefreshGList(&stdgad[FUPG],wind,NULL,2);
  23.     stdgad[FUPG].Flags &= ~SELECTED;
  24.     stdgad[FDPG].Flags &= ~SELECTED;
  25.     TXTOUT(180,21,1,0,cp->name);
  26.     TXTOUT(MESX,MESY,7,0,"... is thinking ...");
  27.     cp->hand[0] = fup[fuptc]; /*test how well next card from fup integrates with other cards*/
  28.     buildsets(cp);
  29.     for(i=0;i<=ncs;i++) score(&cs[i],cp); /*initial scores for sets*/
  30.     n=mutexcl(cp); /*generate non-mutually exclusive combination of submissible sets*/
  31.     if(!n) /*fup card not very useful, and not submissible*/
  32.     { /*try fdp card instead*/
  33.         TXTOUT(MESX,MESY,7,0,"Takes the facedown card.   ");
  34.         takefup=0;
  35.         maintainmem(cp,pp,np,fup[fuptc],GONEPAST);
  36.         maintainmem(cp,pp,np,fup[fuptc],CURRPLRDROPD);
  37.         cp->hand[0]=NEXTFDP;
  38.         cp->mem[CARD2(cp->hand[0])] |= CURRPLRHOLDS;
  39.         buildsets(cp);
  40.         for(i=0;i<=ncs;i++) score(&cs[i],cp);
  41.         mutexcl(cp);
  42.     }
  43.     else
  44.     {
  45.         takefup=1;
  46.         TXTOUT(MESX,MESY,7,0,"Takes the faceup card.   ");
  47.         NEXTFUP;    /*fup card will be used so remove it from pack*/
  48.         maintainmem(cp,pp,np,cp->hand[0],CURRPLRHOLDS);
  49.     }
  50.     for(p=3;p;p--)
  51.     {
  52.         for(n=0;n<=ncs;n++) if(selcs[n].ns) /*some cards in set*/
  53.         {
  54.             s=&selcs[n];
  55.             if((p==3 && s->ns==3 || p==2) && s->type&SUB) autosubset(s,cp); /*submit set*/
  56.             else if(p==1 && s->type&ADD) autoaddset(s,cp); /*add to set*/
  57.         }
  58.     }
  59.     /*now drop card with lowest score*/
  60.     for(i=0,p=60000,n=500;i<=cp->nchld;i++) 
  61.         if(!ISNUL(cp->hand[i]) && (cdsc[i]<p || n==500) && (i!=0 || !takefup)) p=cdsc[n=i]; /*new lowest*/
  62.     PUTFUP(cp->hand[n]);
  63.     DRAWFUP;
  64.     maintainmem(cp,pp,np,cp->hand[n],CURRPLRDROPD);
  65.     cp->hand[n]=nulcard;
  66.     if(!ISNUL(cp->hand[0]))
  67.     { /*copy selected card to body of hand*/
  68.         for(i=1;i<=cp->nchld && !ISNUL(cp->hand[i]);i++);
  69.         cp->hand[i]=cp->hand[0];
  70.     }
  71.     compacthand(cp->hand,&cp->nchld);
  72.     REMHAND(cp);
  73.     if(cp->viewcard) disphand(cp); else hidecards(cp);
  74.     cc-=cp->nchld;
  75.     if(cc)
  76.     {
  77.         sortdispset();
  78.         stci_d(buf,cc);
  79.         TXTOUT(MESX+25*8,MESY,7,0,buf);
  80.         TXTOUT(MESX+27*8,MESY,7,0,"submitted - Hit continue");
  81.     }
  82.     else
  83.     {
  84.         TXTOUT(MESX+25*8,MESY,7,0,"None submitted - Hit continue");
  85.     }
  86.     if(!contplay) WAITCONT;
  87.     AddGList(wind,&stdgad[FUPG],gtemp,2,NULL);
  88.     TXTOUT(MESX,MESY,7,0,"                                                           ");
  89.     TXTOUT(180,21,1,0,"                   ");
  90. }
  91.  
  92. VOID    autosubset(struct condset *s,struct playerinfo *p)
  93. {
  94.     register    struct    card    *t=s->set;
  95.     register    USHORT    i,d,n,samesuit=1,samenum=1;
  96.     for(i=0,n=0;i<=p->nchld;i++) if(!ISNUL(p->hand[i])) n++;
  97.     d=s->ns;
  98.     if(d==n+1)
  99.     {/* ensure at least one card will be left when finished*/
  100.         for(i=0;i<=d;i++) if(CDEQU(p->hand[i],t[d])) s->uc&=~(1<<i);
  101.         d--;
  102.     }
  103.     for(i=2;i<=d;i++)
  104.     { /*final check on validity of set*/
  105.         if(t[i-1].n!=t[i].n) samenum=0;
  106.         if(t[i-1].s!=t[i].s) samesuit=0;
  107.     }
  108.     if(d<3 || !(samesuit || samenum)) return; /*rejected submission attempt*/
  109.     if(samesuit)
  110.     { /*check set is continuous*/
  111.         for(i=2;i<=d;i++)
  112.             if((t[i-1].n!=t[i].n-1) && !(t[i-1].n==KING && t[i].n==ACE)) return; /*rejected*/
  113.     }
  114.     n=s->uc<<1;
  115.     for(i=0;i<=p->nchld;i++) if((n>>=1)&1) p->hand[i]=nulcard; /*this card about to be submitted*/
  116.     for(i=0;i<=5 && fupset[i]->ncard;i++); /*find empty set*/
  117.     fupset[i]->ncard=d;
  118.     if(samesuit) for(n=1;n<=d;n++)
  119.     {
  120.         fupset[i]->cards[n+t[1].n-1]=t[n];
  121.         maintainmem(NULL,NULL,NULL,t[n],INFUPSET);
  122.     }
  123.     else for(n=1;n<=d;n++)
  124.     {
  125.         fupset[i]->cards[n]=t[n];
  126.         maintainmem(NULL,NULL,NULL,t[n],INFUPSET);
  127.     }
  128.     s->ns=s->nd=0; /*remove all cards from set*/
  129. }
  130.  
  131. VOID    autoaddset(struct condset *s,struct playerinfo *p)
  132. {
  133.     register    struct card    *fsc,*phc;
  134.     register    USHORT    *fsn,phn,i,j,f,l,used;
  135.     fsc=fupset[s->addtoset]->cards;
  136.     fsn=&fupset[s->addtoset]->ncard;
  137.     phc=p->hand;
  138.     phn=p->nchld;
  139.     for(f=1;ISNUL(fsc[f]);f++); /*find first card of set*/
  140.     l=f+(*fsn)-1;
  141.     if(fsc[f].s==fsc[f+1].s && s->type&SUITSET) /*same suit*/
  142.     {
  143.         if(s->type&TOSTART)
  144.         {
  145.             if(s->set[1].n==fsc[f].n-1 && s->set[1].s==fsc[f].s)
  146.             {
  147.                 for(i=0,used=1;i<=phn;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
  148.                 {
  149.                     phc[i]=nulcard;
  150.                     used=0; /*card has not already been used*/
  151.                 }
  152.                 if(!used)
  153.                 {
  154.                     fsc[--f]=s->set[1];
  155.                     maintainmem(NULL,NULL,NULL,s->set[1],INFUPSET);
  156.                     (*fsn)++;
  157.                     for(j=1;j<=s->nd;j++) if(s->dep[j].n==fsc[f].n-1 && s->dep[j].s==fsc[f].s)
  158.                     {
  159.                         for(i=0,used=1;i<=phn;i++) if(CDEQU(s->dep[j],phc[i]) && !ISNUL(s->dep[j]))
  160.                         {
  161.                             phc[i]=nulcard;
  162.                             used=0; /*card not already used*/
  163.                         }
  164.                         if(!used)
  165.                         {
  166.                             fsc[--f]=s->dep[j];
  167.                             maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
  168.                             (*fsn)++;
  169.                         }
  170.                         else
  171.                         {/*exit function - no more additions possible*/
  172.                             s->nd=s->ns=0;
  173.                             return;
  174.                         }
  175.                     }
  176.                 }
  177.                 else
  178.                 {/*exit function - no more additions possible*/
  179.                     s->nd=s->ns=0;
  180.                     return;
  181.                 }
  182.             }
  183.         }
  184.         else if(s->type&TOEND)
  185.         {
  186.             if(((s->set[1].n==fsc[l].n+1 && s->set[1].n!=2) || (fsc[l].n==KING && s->set[1].n==ACE))
  187.                 && s->set[1].s==fsc[l].s)
  188.             {
  189.                 for(i=0,used=1;i<=phn;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
  190.                 {
  191.                     phc[i]=nulcard;
  192.                     used=0; /*card not already used*/
  193.                 }
  194.                 if(!used)
  195.                 {
  196.                     fsc[++l]=s->set[1];
  197.                     maintainmem(NULL,NULL,NULL,s->set[1],INFUPSET);
  198.                     (*fsn)++;
  199.                     for(j=1;j<=s->nd;j++) if(((s->dep[j].n==fsc[l].n+1 && s->dep[j].n!=2) || (fsc[l].n==KING && s->dep[j].n==ACE))
  200.                         && s->dep[j].s==fsc[l].s)
  201.                     {
  202.                         for(i=0,used=1;i<=phn;i++) if(CDEQU(s->dep[j],phc[i]) && !ISNUL(s->dep[j]))
  203.                         {
  204.                             phc[i]=nulcard;
  205.                             used=0; /*card not already used*/
  206.                         }
  207.                         if(!used)
  208.                         {
  209.                             fsc[++l]=s->dep[j];
  210.                             maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
  211.                             (*fsn)++;
  212.                         }
  213.                         else
  214.                         {/*exit function - no more additions possible*/
  215.                             s->nd=s->ns=0;
  216.                             return;
  217.                         }
  218.                     }
  219.                 }
  220.                 else
  221.                 {/*exit function - no more additions possible*/
  222.                     s->nd=s->ns=0;
  223.                     return;
  224.                 }
  225.             }
  226.         }
  227.     }
  228.     else if(fsc[f].n==fsc[f+1].n && s->set[1].n==fsc[f].n && s->type&NUMSET && *fsn==3)
  229.     {
  230.         for(i=0,used=1;i<=phn && used;i++) if(CDEQU(s->set[1],phc[i]) && !ISNUL(s->set[1]))
  231.         {
  232.             phc[i]=nulcard;
  233.             used=0; /*card not already used*/
  234.             fsc[++l]=s->set[1];
  235.             maintainmem(NULL,NULL,NULL,s->dep[j],INFUPSET);
  236.             (*fsn)++;
  237.         }
  238.     }
  239.     s->ns=s->nd=0; /*remove all cards from set*/
  240. }
  241.  
  242.             
  243.         
  244. VOID    buildsets(struct playerinfo *p)
  245. {
  246.     register    USHORT    i,n,nchld=p->nchld,s;
  247.     register    struct    card    *h=p->hand;
  248.     USHORT    nconc,setfound;    /*next condensed set, number of consecutive cards*/
  249.     for(i=0;i<=3;i++)
  250.     { /*initialise arrays*/
  251.         for(n=0;n<=15;n++) ss[i].c[n] = nulcard;
  252.         ss[i].nc=0;
  253.     }
  254.     for(i=0;i<=32;i++)
  255.     {
  256.         cs[i].type = NOTSET;
  257.         cs[i].ns = cs[i].nd = cs[i].score = cs[i].ig = cs[i].addtoset = cs[i].uc= 0;
  258.         for(n=0;n<=8;n++) cs[i].set[n]=cs[i].dep[n]=nulcard;
  259.     }
  260.     for(i=0;i<=13;i++) ns[i].nc=0;
  261.  
  262.     for(i=0;i<=nchld;i++)
  263.     { /*separate hand into sets*/
  264.         ns[h[i].n].c[++ns[h[i].n].nc]=h[i];    /*add card to numset*/
  265.         ss[h[i].s].c[h[i].n]=h[i]; /*add card to suit set*/
  266.         if(h[i].n==ACE) ss[h[i].s].c[14]=h[i];
  267.         ss[h[i].s].nc++;
  268.     }
  269.     /*card ss[s].c[n] has suit s and number n.*/
  270.     ncs=0;
  271.     for(i=0;i<=3;i++)
  272.         if(ss[i].nc)
  273.         { /*convert suit set to condensed form*/
  274.             nconc=setfound=0;
  275.             for(n=1;n<=15;n++)
  276.             { /*look for submissible sets*/
  277.                 if(!ISNUL(ss[i].c[n])) nconc++;
  278.                 else
  279.                 {
  280.                     if(nconc>=3)
  281.                     { /*submissible set*/
  282.                         if(setfound) ncs++; /*current set already has submissible subset*/
  283.                         while(nconc) cs[ncs].set[++cs[ncs].ns]=ss[i].c[n-nconc--];
  284.                         setfound=1; /*current record now has a submissible set*/
  285.                         cs[ncs].type = SUITSET | SUB;
  286.                     }
  287.                     else
  288.                     {
  289.                         if((cs[ncs].nd || cs[ncs].ns) && 
  290.                             (n-nconc)-max(cs[ncs].dep[cs[ncs].nd].n,cs[ncs].set[cs[ncs].ns].n)>=(p->nchld<4?p->nchld:4))
  291.                         {
  292.                             ncs++;
  293.                             setfound=0; /*no set in current record*/
  294.                         }
  295.                     while(nconc) cs[ncs].dep[++cs[ncs].nd]=ss[i].c[n-nconc--];
  296.                         cs[ncs].type = SUITSET | SUB;
  297.                     }
  298.                 }
  299.             }
  300.             if(cs[ncs].ns || cs[ncs].nd) cs[ncs++].type = SUITSET | SUB;
  301.             else cs[ncs].ns=cs[ncs].nd=0;
  302.         }
  303.     cs[ncs].type = NOTSET;
  304.  
  305.     /*detect cards which can be added to existing suitsets*/
  306.     for(i=0;i<=3;i++)
  307.     {
  308.         if(ss[i].nc)    /*check some cards in set*/
  309.         {
  310.             for(n=1;n<=14;n++)
  311.             {
  312.                 if(!ISNUL(ss[i].c[n]))
  313.                 {
  314.                     setfound=0;
  315.                     for(s=0;s<=5 && !setfound && fupset[s]->ncard;s++)
  316.                     {
  317.                         if(ISNUL(fupset[s]->cards[n]))
  318.                         {
  319.                             if(fupset[s]->cards[n-1].n==n-1 && !ISNUL(fupset[s]->cards[n-1])
  320.                                 && fupset[s]->cards[n-1].s==i && fupset[s]->cards[n-2].s==i)
  321.                             { /*can add after set s*/
  322.                                 if(cs[ncs].type!=NOTSET) ncs++; /*current set already used*/
  323.                                 else cs[ncs].ns=cs[ncs].nd=0; /*current set no good - throw it away*/
  324.                                 cs[ncs].set[++cs[ncs].ns]=ss[i].c[n];
  325.                                 cs[ncs].addtoset=s;
  326.                                 cs[ncs].type = ADD | SUITSET | TOEND;
  327.                                 setfound=1;
  328.                             }
  329.                             else if(fupset[s]->cards[n+1].n==n+1 && fupset[s]->cards[n+1].s==i && fupset[s]->cards[n+2].s==i)
  330.                             { /*can add before set s*/
  331.                                 if(cs[ncs].type!=NOTSET || (cs[ncs].nd && cs[ncs].dep[1].s!=ss[i].c[n].s)) ncs++;
  332.                                 cs[ncs].set[++cs[ncs].ns]=ss[i].c[n];
  333.                                 cs[ncs].addtoset=s;
  334.                                 cs[ncs].type= ADD | SUITSET | TOSTART;
  335.                                 setfound=1;
  336.                                 ncs++; /*move to new set*/
  337.                             }
  338.                         }
  339.                     }
  340.                     if(!setfound)
  341.                     { /*add to dependants*/
  342.                         if((cs[ncs].ns || cs[ncs].nd)
  343.                             && ((n-max(cs[ncs].set[cs[ncs].ns].n,cs[ncs].dep[cs[ncs].nd].n))>=4)
  344.                             || (ss[i].c[n].s!=(cs[ncs].ns==0?cs[ncs].dep[1].s:cs[ncs].set[1].s)))
  345.                         { /*start new set*/
  346.                             if(cs[ncs].type!=NOTSET) ncs++;
  347.                             else cs[ncs].ns=cs[ncs].nd=0;
  348.                         }
  349.                         cs[ncs].dep[++cs[ncs].nd]=ss[i].c[n];
  350.                     }
  351.                 }
  352.             }
  353.         }
  354.     }
  355.     if(cs[ncs].ns) ncs++;
  356.     else cs[ncs].nd=0;
  357.  
  358.     /*copy numsets to condensed sets*/
  359.     for(i=1;i<=13;i++)
  360.     {
  361.         if(ns[i].nc==1)
  362.         { /*can card be added to existing set*/
  363.             setfound=0;
  364.             for(s=0;s<=5 && !setfound && fupset[s]->ncard;s++)
  365.                 if(fupset[s]->cards[1].n==ns[i].c[1].n && fupset[s]->cards[2].n==ns[i].c[1].n)
  366.                 { /*can add card this set*/
  367.                     cs[ncs].addtoset=s;
  368.                     cs[ncs].set[++cs[ncs].ns]=ns[i].c[1];
  369.                     cs[ncs++].type= ADD | NUMSET;
  370.                     setfound=1;
  371.                 }
  372.             if(!setfound)
  373.             {
  374.                 cs[ncs].dep[++cs[ncs].nd]=ns[i].c[1];
  375.                 cs[ncs++].type = SUB | NUMSET;
  376.             }
  377.         }
  378.         else if(ns[i].nc==2)
  379.         {
  380.             cs[ncs].dep[1]=ns[i].c[1];
  381.             cs[ncs].dep[2]=ns[i].c[2];
  382.             cs[ncs].type = NUMSET | SUB;
  383.             cs[ncs++].nd=2;
  384.         }
  385.         else if(ns[i].nc>=3)
  386.         {
  387.             for(n=1;n<=ns[i].nc;n++) cs[ncs].set[n]=ns[i].c[n];
  388.             cs[ncs].type = NUMSET | SUB;
  389.             cs[ncs++].ns=ns[i].nc;
  390.         }
  391.     }
  392.     for(i=0;i<=ncs;i++)
  393.         for(n=1;n<=cs[i].ns;n++)
  394.             for(s=setfound=0;s<=nchld && !setfound;s++) if(setfound=CDEQU(cs[i].set[n],h[s])) cs[i].uc|=(1<<s);
  395. }
  396.  
  397. VOID    score(struct condset *c,struct playerinfo *p)
  398. {
  399.     register    USHORT    i,n,j,last,m,s;
  400.     USHORT    gap,next;
  401.     struct    card    t[5];
  402.     c->score = 0;
  403.     if(c->type&NUMSET)
  404.     {
  405.         for(n=1;n<=c->ns;n++) c->score+=(c->set[n].n*8+(n>1?1100:0))+300;
  406.         for(n=1;n<=c->nd;n++) c->score+=((15-c->dep[n].n)*4+(n>1?1300:0));
  407.         for(n=1;n<=4;n++) t[n]=nulcard;
  408.         if(c->nd)
  409.         {
  410.             s=c->dep[1].n;
  411.             for(n=1;n<=c->nd;n++) t[c->dep[n].s]=c->dep[n];
  412.         }
  413.         else
  414.         {
  415.             s=c->set[1].n;
  416.             for(n=1;n<=c->ns;n++) t[c->set[n].s]=c->set[n];
  417.         }
  418.         for(n=1;n<=4;n++) if(ISNUL(t[n]))
  419.         {
  420.             m=p->mem[CARD(s,n)];
  421.             if(!(m&INFUPSET))
  422.             {
  423.                 c->score+=100+15-s;
  424.                 if(!(m&NEXTPLRHOLDS)) c->score+=70;
  425.                 if(!(m&PREVPLRHOLDS)) c->score+=40;
  426.                 if(!(m&GONEPAST)) c->score+=100;
  427.                 if(m&(NEXTPLRDROPD | PREVPLRDROPD)) c->score+=100;
  428.             }
  429.         }
  430.         else c->score+=(16-t[n].n)*4;
  431.     }
  432.     else /*score suitset*/
  433.     {
  434.         if(ISNUL(c->set[1])) last=c->dep[1].n;
  435.         else if(ISNUL(c->dep[1])) last=c->set[1].n;
  436.         else last=min(c->dep[1].n,c->set[1].n);
  437.         if(c->type&SUB)
  438.         {
  439.             c->score+=c->ns*500+c->nd*100;
  440.             for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
  441.             {
  442.                 if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
  443.                 {
  444.                     if(c->set[i].n==ACE && i>1) c->score+=(last==KING?1200:(7-(13-last))*130)+15*9+100;
  445.                     else if(c->set[i].n!=last)
  446.                         c->score+=(c->set[i].n-last==1?1200:(6-(c->set[i].n-last-1))*100)+c->set[i].n*9+100;
  447.                     else c->score+=(15-last)*9+100;
  448.                     last=c->set[i++].n;
  449.                 }
  450.                 else
  451.                 {
  452.                     if(c->dep[n].n==ACE && n>1) c->score+=(last==KING?1200:(6-(13-last))*110)+15*5+80;
  453.                     else if(c->dep[n].n!=last)
  454.                         c->score+=(c->dep[n].n-last==1?1200:(6-(c->dep[n].n-last-1))*90)+(15-c->dep[n].n)*5+80;
  455.                     else c->score+=(15-last)*5+80;
  456.                     last=c->dep[n++].n;
  457.                 }
  458.             }
  459.         }
  460.         else if(c->type&ADD)
  461.         {
  462.             for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
  463.             {
  464.                 if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
  465.                 {
  466.                     if(c->set[i].n==ACE && i>1) next = 14;
  467.                     else next=c->set[i].n;
  468.                     if(last!=c->set[i].n)
  469.                         c->score+=(next-last==1?1200:(7-(next-last-1))*100)+c->set[i].n*9+100;
  470.                     else c->score+=(15-last)*9+100;
  471.                     last=c->set[i++].n;
  472.                 }
  473.                 else
  474.                 {
  475.                     if(c->dep[n].n==ACE && i>1) next = 14;
  476.                     else next=c->dep[n].n;
  477.                     if(next-last==1) c->score+=1200+c->dep[n].n*8+80;
  478.                     else if(last!=next) c->score+=(6-(next-last-1))*90+c->dep[n].n*5+80;
  479.                     else c->score+=(15-last)*5+80;
  480.                     last=c->dep[n++].n;
  481.                 }
  482.             }
  483.         }
  484.         
  485.         if(!ISNUL(c->set[1])) s=c->set[1].s;
  486.         else s=c->dep[1].s;
  487.         if(ISNUL(c->set[1])) last=c->dep[1].n;
  488.         else if(ISNUL(c->dep[1])) last=c->set[1].n;
  489.         else last=min(c->dep[1].n,c->set[1].n);
  490.         for(i=n=1;(i<=c->ns || n<=c->nd) && !exgm && !quit;)
  491.         {
  492.             if(c->set[i].n<=c->dep[n].n && i<=c->ns || n>c->nd)
  493.             {
  494.                 gap=c->set[i].n-last-1;
  495.                 next=c->set[i++].n;
  496.             }
  497.             else
  498.             {
  499.                 gap=c->dep[n].n-last-1;
  500.                 next=c->dep[n++].n;
  501.             }
  502.             for(j=last+1;j<next;j++)
  503.             {
  504.                 m=p->mem[CARD(s,n)];
  505.                 if(!(m&INFUPSET))
  506.                 {
  507.                     c->score+=90/gap+15-s;
  508.                     if(!(m&NEXTPLRHOLDS)) c->score+=70/gap;
  509.                     if(!(m&PREVPLRHOLDS)) c->score+=70/gap;
  510.                     if(!(m&GONEPAST)) c->score+=90/gap;
  511.                     if(m&(NEXTPLRDROPD | PREVPLRDROPD)) c->score+=90/gap;
  512.                 }
  513.                 last=next;
  514.             }
  515.         }
  516.     }
  517.     if(c->type&SUB && p->nchld<=2) c->score=0; /*less than useless*/
  518.     if(c->type&ADD && p->nchld<=2) c->score+=15000; /*ensure high score for addable sets when submission is impossible*/
  519.     if(c->type&NUMSET && c->nd==2) c->score+=500;
  520.     c->score+=c->ns*600;
  521. }
  522.  
  523. USHORT    mutexcl(struct playerinfo *p)
  524. {
  525.     register    USHORT    i,j,k,w,x;
  526.     long    l;
  527.     struct    card    c,*s;
  528.     USHORT    bias,    /*toward 1:numset, 2:suitset 3:set with higher score*/
  529.         pass,    /*number of passes to be made with different biases*/
  530.         nxsts,    /*next start set*/
  531.         psperbias,    /*number of passes to be made for each bias at different start sets*/
  532.         best=0,pn,chng,currst,pm,sc,cdscs[53];
  533.     if(p->level==1)
  534.     {/*easiest level*/
  535.         bias=1; pass=1; nxsts=0; psperbias=1;
  536.     }
  537.     else if(p->level==1)
  538.     {/*best level*/
  539.         bias=1; pass=3; nxsts=0; psperbias=ncs;
  540.     }
  541.     else if(p->level<=5)
  542.     {/*fairly easy*/
  543.         l=rand();
  544.         bias=1;
  545.         pass=1;
  546.         if((nxsts=l&31)>ncs) nxsts=ncs;
  547.         if((psperbias=(l>>5&31)+1)>ncs>>1 && ncs!=1) psperbias=ncs>>1;
  548.     }
  549.     else
  550.     {/*fairly good play*/
  551.         l=rand();
  552.         bias=1;
  553.         pass=3;
  554.         if((nxsts=l&31)>ncs) nxsts=ncs;
  555.         if((psperbias=(l>>5&31)+1)>ncs) psperbias=ncs;
  556.     }
  557.  
  558.     while(pass--)
  559.     {
  560.         for(currst=nxsts,pn=psperbias,chng=1;pn && chng;pn--)
  561.         {
  562.             chng=0;    /*change made flag*/
  563.             for(i=0;i<=ncs;i++) testcs[i]=cs[i];
  564.             for(i=currst,pm=0;!pm || i!=currst;i=i>=ncs?0:i+1)
  565.             {
  566.                 pm=1;
  567.                 for(j=(i>=ncs?0:i+1);j!=i;j=j>=ncs?0:j+1)
  568.                 {
  569.                     if(w=testcs[i].uc&testcs[j].uc)
  570.                     {/*collision between sets*/
  571.                         w<<=1;k=0;
  572.                         while(w)
  573.                         {
  574.                             while(!((w>>=1)&1) && w) k++;
  575.                             c=p->hand[k];    /*card causing collision*/
  576.                             if(w && ((bias==1 && testcs[i].type&NUMSET && testcs[j].type&SUITSET)
  577.                                 || (bias==2 && testcs[i].score >= testcs[j].score)
  578.                                 || (bias==3 && testcs[i].score < testcs[j].score)))
  579.                             { /*reduce set i*/
  580.                                 chng=1;
  581.                                 for(x=1;!CDEQU(testcs[i].set[x],c) && x<=testcs[i].ns;x++);
  582.                                 testcs[i].set[x]=nulcard;
  583.                                 if(c.n==ACE && testcs[i].set[testcs[i].ns].n==ACE) testcs[i].set[testcs[i].ns]=nulcard;
  584.                                 compacthand(testcs[i].set,&testcs[i].ns);
  585.                                 checksets(&testcs[i],p);
  586.                                 score(&testcs[i],p);
  587.                             }
  588.                             else if(w)
  589.                             { /*reduce set j*/
  590.                                 chng=1;
  591.                                 for(x=1;!CDEQU(testcs[j].set[x],c) && x<=testcs[j].ns;x++);
  592.                                 testcs[j].set[x]=nulcard;
  593.                                 if(c.n==ACE && testcs[j].set[testcs[j].ns].n==ACE) testcs[j].set[testcs[j].ns]=nulcard;
  594.                                 compacthand(testcs[j].set,&testcs[j].ns);
  595.                                 checksets(&testcs[j],p);
  596.                                 score(&testcs[j],p);
  597.                             }
  598.                         }
  599.                     }
  600.                 }
  601.             }
  602.             for(j=0,sc=0;j<=ncs;j++) sc+=testcs[j].score;
  603.             if(sc>best)
  604.             { /*new best set*/
  605.                 best=sc;
  606.                 for(j=0;j<=ncs;j++) selcs[j]=testcs[j];
  607.             }
  608.             if(currst==ncs) currst=0; else currst++;
  609.             if(bias==3) bias=1; else bias++;
  610.         }
  611.     }
  612.     
  613.     for(j=0;j<=p->nchld;j++) cdscs[CARD2(p->hand[j])]=0; /*zeroise scores of player cards*/
  614.     /* The section below prevents the autoplayer being left with just two
  615.      * cards, which cannot be submitted (min 3), and meaning it must wait
  616.      * for cards to arrive which can be added to existing sets, which the
  617.      * other players will also be looking out for.
  618.      * NB. this will only reduce submissions by one card, and only where
  619.      * permissible.
  620.      */
  621.     /*work out number of cards to be submitted by this combination of sets*/
  622.     for(i=0,w=0;i<=ncs;i++) if(selcs[i].type&ADD)
  623.     {
  624.         w++; /*at least one card can be submitted*/
  625.         for(j=1,x=selcs[i].set[1].n;j<=selcs[i].nd;j++) if(x+1==selcs[i].dep[j].n || x-1==selcs[i].dep[j].n)
  626.         {
  627.             w++; x=selcs[i].dep[j].n;
  628.         }
  629.     }
  630.     else if(selcs[i].type&SUB) w+=selcs[i].ns;
  631.     if(p->nchld-w==2) /*retain one further card to enable later submissions*/
  632.     {
  633.         for(i=0,w=0;i<=ncs && !w;i++) if(selcs[i].type&SUB && selcs[i].ns>=4)
  634.         {/*prevent submission of one of the cards of the set*/
  635.             for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
  636.             selcs[i].dep[1]=selcs[i].set[selcs[i].ns--];
  637.             selcs[i].nd++;
  638.             w=1; /*finished*/
  639.             cdscs[CARD2(selcs[i].dep[1])]+=20000; /*ensure this card retained*/
  640.         }
  641.         else if(selcs[i].type&ADD)
  642.         {
  643.             if(selcs[i].type&NUMSET || (selcs[i].type&SUITSET 
  644.                 && selcs[i].set[1].n!=selcs[i].dep[1].n-1 && selcs[i].set[1].n!=selcs[i].dep[1].n+1))
  645.             {/* only one addable card - remove it to the dep list*/
  646.                 for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
  647.                 selcs[i].dep[1]=selcs[i].set[1];
  648.                 selcs[i].set[1]=nulcard;
  649.                 selcs[i].ns--; selcs[i].nd++;
  650.                 selcs[i].type&= ~ADD;
  651.                 selcs[i].type|= SUB;
  652.                 w=1;
  653.                 cdscs[CARD2(selcs[i].dep[1])]+=20000; /*ensure this card retained*/
  654.             }
  655.             else
  656.             {/* reduce number of addable cards of this set to just one*/
  657.                 for(j=selcs[i].nd;j>=2;j--) selcs[i].dep[j]=selcs[i].dep[j-1]; /*create space in dep list*/
  658.                 selcs[i].dep[1]=nulcard;
  659.                 selcs[i].nd++;
  660.                 cdscs[CARD2(selcs[i].dep[2])]+=20000; /*ensure this card retained*/
  661.                 w=1;
  662.             }
  663.         }
  664.     }
  665.                 
  666.     /*generate card scores here*/
  667.     for(i=0;i<=ncs;i++)
  668.     {
  669.         if(selcs[i].type&SUITSET)
  670.         {
  671.             if(selcs[i].ns)
  672.             {
  673.                 for(j=1;j<=selcs[i].ns;j++) cdscs[CARD2(selcs[i].set[j])]+=selcs[i].score;
  674.                 for(j=1;j<=selcs[i].nd;j++) 
  675.                 {
  676.                     w=selcs[i].dep[j-1].n;x=selcs[i].dep[j].n;
  677.                     k=selcs[i].dep[j+1].n;
  678.                     if(selcs[i].dep[j].n<selcs[i].set[1].n)
  679.                     cdscs[CARD2(selcs[i].dep[j])]+=(selcs[i].score*j)/22 +
  680.                         ((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/30 +
  681.                         ((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/30;
  682.  
  683.                     else cdscs[CARD2(selcs[i].dep[j])]+=(selcs[i].score*(9-j))/22 +
  684.                         ((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/30 +
  685.                         ((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/30;
  686.                 }
  687.             }
  688.             else /*no submissible cards*/
  689.             {
  690.                 for(j=1;j<=selcs[i].nd;j++)
  691.                 {
  692.                     w=selcs[i].dep[j-1].n;x=selcs[i].dep[j].n;
  693.                     k=selcs[i].dep[j+1].n;
  694.                     cdscs[CARD2(selcs[i].dep[j])]+=selcs[i].score +
  695.                         ((j>1?(w<x?x-w:w-x):0) * selcs[i].score)/12 +
  696.                         ((j<selcs[i].nd?(k<x?x-k:k-x):0) * selcs[i].score)/12;
  697.                 }
  698.             }
  699.         }
  700.         else /*numset*/
  701.         {
  702.             for(j=1;j<=selcs[i].ns;j++) cdscs[CARD2(selcs[i].set[j])]+=selcs[i].score*(j==4?(1/2):1);
  703.             for(j=1;j<=selcs[i].nd;j++) cdscs[CARD2(selcs[i].dep[j])]+=selcs[i].score*(j==4?(1/2):1);
  704.         }
  705.     }
  706.  
  707.     for(j=0;j<=p->nchld;j++) cdsc[j]=cdscs[CARD2(p->hand[j])];
  708.     l=rand();
  709.     if(p->level==1) return (USHORT)(l&1);
  710.     else if(p->level<=9)
  711.     {
  712.         if(p->level<(l%11)+1) return (USHORT)(l&256);
  713.     }
  714.     
  715.     /* the next loop checks to see if any cards can be added to an existing
  716.      * set after the acquisition of one further card, a facility which was
  717.      * overlooked in the original program design
  718.      */
  719.     for(i=0;i<=p->nchld;i++)
  720.     {
  721.         for(j=0;j<5 && fupset[j]->ncard;j++)
  722.         {
  723.             s=fupset[j]->cards;
  724.             for(k=1;k<=13 && ISNUL(s[k]);k++);
  725.             w=k+fupset[j]->ncard-1; /*last card*/
  726.             if(s[k].s==s[k+1].s && s[k].s==p->hand[i].s) /*suitset*/
  727.             {
  728.                 x=p->hand[i].n;
  729.                 if(x==s[k].n-2 && !(p->mem[CARD(x+1,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
  730.                 if(x==s[w].n+2 && !(p->mem[CARD(x-1,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
  731.                 if(x==ACE && s[w].n==QUEEN && !(p->mem[CARD(KING,s[k].s)]&INFUPSET)) cdsc[i]+=1500;
  732.             }
  733.         }
  734.     }
  735.     
  736.     if(p->nchld==1)
  737.     {
  738.         for(i=0;i<=ncs;i++) if(selcs[i].type&ADD && CDEQU(selcs[i].set[1],p->hand[0])) return 1;
  739.         return 0; /* last card not addable, so recommend to ignore it*/
  740.     }
  741.     
  742.     /* the section below causes the last selected card to be dropped if it
  743.      * only belongs to one set of two cards, and the other member is about
  744.      * to be dropped
  745.      */
  746.     j=cdsc[k=0];
  747.     for(i=1;i<=p->nchld;i++) if(cdsc[i]<j) j=cdsc[k=i];
  748.     if(k!=0 && cdsc[0]>1690 /* || cdsc[0]>2200*/) return 1; /*keep last selected card*/
  749.     else 
  750.     {
  751.         for(i=w=x=0;i<=ncs;i++)
  752.         {
  753.             for(j=1;j<=selcs[i].nd;j++) if(CDEQU(selcs[i].dep[j],p->hand[0]) && selcs[i].nd==2 && !selcs[i].ns)
  754.             {
  755.                 w++;
  756.                 x=i;
  757.             }
  758.         }
  759.         if(w==1)
  760.         {
  761.             if(CDEQU(selcs[x].dep[1],p->hand[0])) j=2; else j=1;
  762.             for(i=0;i<=p->nchld;i++) if(CDEQU(p->hand[i],selcs[x].dep[j]) && i==k) return 0; /*drop card*/
  763.         }
  764.     }
  765.     
  766.     for(j=0;j<=ncs;j++) if(selcs[j].uc&1) return 1; /* last chosen card being submitted in set*/
  767.     return 0; /*last selected card not being submitted in a set,
  768.                 and not within two of an adjacent card*/
  769. }
  770.  
  771.  
  772. VOID    checksets(struct condset *c,struct playerinfo *p)
  773. { /*reconstruct reduced set*/
  774.     register    USHORT    i,n=0,nconc,setfound;
  775.     struct    card    t[16];
  776.     for(i=0;i<=15;i++) t[i]=nulcard;
  777.     if(c->type&SUITSET && c->type&SUB)
  778.     {
  779.         for(i=1;i<=c->ns;i++) if(c->set[i].n==ACE && i>1) t[14]=c->set[i];
  780.             else t[c->set[i].n]=c->set[i];
  781.         for(i=1;i<=c->nd;i++) if(c->dep[i].n==ACE && i>1) t[14]=c->dep[i];
  782.             else t[c->dep[i].n]=c->dep[i];
  783.         n=c->nd+c->ns;
  784.         nconc=0;
  785.         c->nd=c->ns=0;
  786.         for(i=1;i<=15;i++)
  787.         {
  788.             if(!ISNUL(t[i])) nconc++;
  789.             else
  790.             {
  791.                 if(nconc>=3) while(nconc) c->set[++c->ns]=t[i-nconc--];
  792.                 else while(nconc) c->dep[++c->nd]=t[i-nconc--];
  793.             }
  794.         }
  795.     }
  796.     else if(c->type&NUMSET && c->type&SUB)
  797.     {
  798.         if(c->ns==2 || c->ns==1) for(c->nd=0;c->ns;)c->dep[++c->nd]=c->set[c->ns--];
  799.     }
  800.     if(!(c->ns || c->nd)) c->type=NOTSET;    /*no cards in this set*/
  801.     else for(n=1,c->uc=0;n<=c->ns;n++)
  802.         for(i=setfound=0;i<=p->nchld && !setfound;i++) if(setfound=CDEQU(c->set[n],p->hand[i])) c->uc|=(1<<i);
  803.  
  804. }
  805.